home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 4
/
Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso
/
Pearls
/
comm
/
Network
/
ProNET
/
source
/
device
/
pronet.device.s
Wrap
Text File
|
1995-06-22
|
19KB
|
980 lines
**
** ProNET.DEVICE Version 2 ©1995 by Michael Krause
** Most parts totally recoded, only few parts left from V1
**
** 05-05-95 Started
** 08-05-95 v35.0
** 31-05-95 If the pending writes list is not empty before the MainLoop
** Wait(), we will signal ourselves to call msgREAD! This is
** because otherwise a timeout while sending would cause the
** device to hang completely, if the other machine doesn't
** send something! v35.1
** 05-06-95 Flags Argument for Driver-Init. v35.2
** 09-06-95 Getconfigstring uses MEMF_PUBLIC for Read Buffer. v35.3
** 15-06-95 PNDERR_DRIVERTROUBLE introduced. v35.4
VERSION equ 35
REVISION equ 4
DEBUG equ 0
include "A:OSmacros.i"
include "exec/exec.i"
include "dos/dosextens.i"
include "A:ProNET/include/devices/pronet.i"
include "exec_lib.i"
include "dos_lib.i"
moveq #-1,d0
rts
** -----------------------------------------------------------------------
**
**
**
**
**
** Library/Device Base Structures
**
**
**
**
**
** -----------------------------------------------------------------------
STRUCTURE MyDev,LIB_SIZE ;Device Base
APTR pnd_SegList
APTR pnd_DosBase
LABEL pnd_SizeOf
STRUCTURE MyUnit,0 ;Unit Structure
APTR pndu_Next
ULONG pndu_UnitNr
APTR pndu_ProcessID
APTR pndu_MsgPort
LABEL pndu_SizeOf
STRUCTURE PortMember,0 ;One Port of a Unit
APTR pndp_Next
UWORD pndp_PortNr
ULONG pndp_MsgPort
LABEL pndp_SizeOf
PND_ADDPORT equ 5
PND_REMPORT equ 6
LibResident dc.w RTC_MATCHWORD
dc.l LibResident
dc.l EndResident
dc.b RTF_AUTOINIT
dc.b VERSION
dc.b NT_DEVICE
dc.b 0
dc.l DevName
dc.l IDString
dc.l LibInitData
DevName dc.b "pronet.device",0
dc.b "$VER: "
IDString dc.b "pronet.device "
dc.b (VERSION/10)+48,(VERSION-((VERSION/10)*10))+48,".",REVISION+48
dc.b " (09-06-95)",13,10,0
even
LibInitData dc.l pnd_SizeOf
dc.l FuncTab
dc.l DataTab
dc.l LibInitRout
FuncTab dc.l Open
dc.l Close
dc.l Expunge
dc.l ExtFunc
dc.l BeginIO
dc.l AbortIO
dc.l getconfigstr
dc.l freeconfigstr
dc.l -1
DataTab INITBYTE LN_TYPE,NT_DEVICE
INITLONG LN_NAME,DevName
INITBYTE LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
INITWORD LIB_VERSION,VERSION
INITWORD LIB_REVISION,REVISION
INITLONG LIB_IDSTRING,IDString
dc.w 0
OurBase dc.l 0
** -----------------------------------------------------------------------
**
**
**
**
**
** Library/Device Base Routines
**
**
**
**
**
** -----------------------------------------------------------------------
; -- Called once when the device was loaded
LibInitRout movem.l d1-d7/a0-a6,-(sp)
move.l d0,a5
move.l a5,OurBase
move.l a0,pnd_SegList(a5)
lea dosname(pc),a1
moveq #0,d0
LIBCALL OpenLibrary
move.l d0,pnd_DosBase(a5)
move.l a5,d0
movem.l (sp)+,d1-d7/a0-a6
rts
; -- This piece is called by OpenDevice()
Open movem.l a2-a6/d2-d7,-(sp)
addq.w #1,LIB_OPENCNT(a6)
move.l d0,d6 ;Unit
move.l a1,a2 ;IORequest
move.l a6,a5 ;DevBase
move.b #IOERR_OPENFAIL,IO_ERROR(a2)
* Does the required Unit already exist?
lea unitlist(pc),a3
.searchunit move.l (a3),d0
beq.s .newunit
move.l d0,a3
cmp.l pndu_UnitNr(a3),d6
bne.s .searchunit
bra.s .unitok
* No! So create a Unit!
.newunit bsr InitUnit
tst.l d0
beq .ende
move.l d0,a3
* Yes! Add new port now! Unit-Structure in a3
.unitok move.l 4.w,a6
move.w #PND_ADDPORT,IO_COMMAND(a2)
move.l a2,a1
move.l pndu_MsgPort(a3),a0
LIBCALL PutMsg
move.l a2,a1
LIBCALL WaitIO
tst.b d0
bne.s .ende
move.l a3,IO_UNIT(a2)
* Device successfully opened.
move.l a5,a6
bclr #LIBB_DELEXP,LIB_FLAGS(a6)
addq.w #1,LIB_OPENCNT(a6)
move.b #NT_REPLYMSG,LN_TYPE(a2)
clr.b IO_ERROR(a2)
.ende move.l a5,a6
subq.w #1,LIB_OPENCNT(a6)
move.b IO_ERROR(a2),d0
beq.s .0
move.l #-1,IO_DEVICE(a2)
.0 movem.l (sp)+,a2-a6/d2-d7
rts
; -- Called by CloseDevice()
Close movem.l a2/a5,-(sp)
move.l a1,a2
move.l a6,a5
move.l 4.w,a6
move.l IO_UNIT(a1),a0
move.l pndu_MsgPort(a0),a0
move.w #PND_REMPORT,IO_COMMAND(a1)
LIBCALL PutMsg
move.l a2,a1
LIBCALL WaitIO
move.l a2,a1
move.l a5,a6
move.l #-1,IO_DEVICE(a1)
move.l #-1,IO_UNIT(a1)
subq.w #1,LIB_OPENCNT(a6)
moveq #0,d0
movem.l (sp)+,a2/a5
rts
; -- This routine was kept free by Commodore for about 10 years now ;)
ExtFunc moveq #0,d0
rts
; -- Application wants an IORequest to be executed
BeginIO move.l a6,-(sp)
move.b #NT_MESSAGE,LN_TYPE(a1)
bclr #0,IO_FLAGS(a1) ;Clear IOF_QUICK
clr.b IO_ERROR(a1)
move.l IO_UNIT(a1),a0
move.l pndu_MsgPort(a0),a0
move.l 4.w,a6
LIBCALL PutMsg
moveq #0,d0
move.l (sp)+,a6
rts
; -- AbortIO is not supported
AbortIO moveq #0,d0 ;Gar nix geht ab hier.
rts
; -- Called e.g. when memory is low and the device is not used anymore.
Expunge movem.l d1-d2/a1-a6,-(sp)
moveq #0,d0
bset #LIBB_DELEXP,LIB_FLAGS(a6) ;we don't support
movem.l (sp)+,d1-d2/a1-a6 ;expunging!
rts
; -- Create new Unit
InitUnit ; a5 *DevBase
; a2 *IORequest
; d6 Unit
; RETURNS d0 *Unit-Structure or NULL
move.l 4.w,a6
moveq #pndu_SizeOf,d0
moveq #MEMF_PUBLIC,d1
LIBCALL AllocMem
tst.l d0
beq.s .ende
move.l d0,a3
move.l d6,pndu_UnitNr(a3)
* First, create Unit process
move.l pnd_DosBase(a5),a6 ;We will break the Forbid()
move.l #DevName,d1 ;which EXEC made for us;
moveq #0,d2 ;it's okay because we have
move.l #ProcessCode-4,d3 ;all variables in registers,
lsr.l #2,d3 ;so our routine can be run
move.l #4096,d4 ;twice at one time without
LIBCALL CreateProc ;problems!
move.l d0,d7
beq.s .ende
move.l d7,pndu_ProcessID(a3)
* Notify process about Unit number
move.l 4.w,a6
move.l a2,a1
move.l a3,pnr_Data2(a1)
move.b IO_ERROR(a2),d2 ;save it for the main routine
move.l d7,a0
LIBCALL PutMsg
* Wait for Process to finish initialization
move.l a2,a1
LIBCALL WaitIO
move.b d2,IO_ERROR(a2)
tst.b d0
bne.s .error
* Now add this Unit-Structure to our internal List!!
LIBCALL Forbid ;<< important!
lea unitlist(pc),a0
move.l (a0),(a3)
move.l a3,(a0)
LIBCALL Permit
move.l a3,d0
rts
.error move.l 4.w,a6 ;Process will terminate
move.l a3,a1 ;itself in case of an error
moveq #pndu_SizeOf,d0
LIBCALL FreeMem
.ende moveq #0,d0
rts
unitlist dc.l 0 ;List of all Units loaded!
** -----------------------------------------------------------------------
**
**
**
**
**
** DeviceUnit Process Code
**
**
**
**
**
** -----------------------------------------------------------------------
cnop 0,4
STRUCTURE PrivateData,0
APTR priv_OurUnit
STRUCT priv_ConfigStringName,30
APTR priv_ConfigString
STRUCT priv_DriverName,30
LABEL priv_DriverData
UBYTE priv_ReadSignalBit
UBYTE priv_pad0
APTR priv_ReadQuery
APTR priv_Read
APTR priv_Write
APTR priv_MsgPort
APTR priv_MsgBackPort
APTR priv_PortList
STRUCT priv_PendingReads,12
STRUCT priv_PendingWrites,12
LABEL priv_SizeOf
ProcessCode move.l 4.w,a6
move.l ThisTask(a6),a2
lea pr_MsgPort(a2),a2
move.l a2,a0
LIBCALL WaitPort
move.l a2,a0
LIBCALL GetMsg
move.l d0,a3
move.b #IOERR_OPENFAIL,IO_ERROR(a3) ;[a3] Startupmsg
* Get memory for private data
moveq #priv_SizeOf,d0
move.l #MEMF_CLEAR,d1
LIBCALL AllocMem
tst.l d0
beq .ende
move.l d0,a5
lea priv_PendingReads(a5),a1
NEWLIST a1
lea priv_PendingWrites(a5),a1
NEWLIST a1
* Get port for messages replied from the application
bsr CreatePort
move.l d0,priv_MsgBackPort(a5)
beq.s .noconf
bsr CreatePort
move.l d0,priv_MsgPort(a5)
beq.s .noport2
move.l pnr_Data2(a3),a0
move.l a0,priv_OurUnit(a5)
move.l priv_MsgPort(a5),pndu_MsgPort(a0)
* Get configuration string for our unit
move.l pndu_UnitNr(a0),d0
lea confstr(pc),a1
lea priv_ConfigStringName(a5),a0
.l0 move.b (a1)+,(a0)+
bne.s .l0
subq.l #1,a0
bsr long2dec
move.b #":",(a0)+
clr.b (a0)
lea priv_ConfigStringName(a5),a0
bsr getconfigstr
move.l d0,priv_ConfigString(a5)
beq.s .noconf
move.b #PNDERR_DRIVERTROUBLE,IO_ERROR(a3)
bsr StartDriver
tst.l d0
beq.s .noconf
clr.b IO_ERROR(a3)
move.l a3,a1
LIBCALL ReplyMsg
bra MainLoop
.noport2 move.l priv_MsgBackPort(a5),a0
bsr DeletePort
.noconf move.l a5,a1
moveq #priv_SizeOf,d0
LIBCALL FreeMem
.ende move.l a3,a1
LIBCALL ReplyMsg
rts
confstr dc.b "pronet-device-",0
even
; -- Load the interface driver and initialize it.
StartDriver ; RETURNS d0 NULL on failure!
movem.l a2/a6,-(sp)
lea priv_DriverName(a5),a1
move.l a1,d1
lea drivername(pc),a0
.l0 move.b (a0)+,(a1)+
bne.s .l0
subq.l #1,a1
move.l priv_ConfigString(a5),a0
.l1 move.b (a0)+,d0
move.b d0,(a1)+
cmp.b #" ",d0
bhi.s .l1
clr.b -(a1)
move.l a0,d6
move.l OurBase(pc),a6 ;naahh why should I open
move.l pnd_DosBase(a6),a6 ;it again??
LIBCALL LoadSeg
add.l d0,d0
add.l d0,d0
beq.s .error
addq.l #4,d0
move.l d0,a2
* And now, Ladies & Gentlemen :))
lea priv_DriverData(a5),a0
move.l d6,a1 ;ConfString after Driver-ID
move.l #"RST!",d0
moveq #0,d1
jsr (a2)
tst.l d0
beq.s .error
moveq #-1,d0
bra.s .ende
.error moveq #0,d0
.ende movem.l (sp)+,a2/a6
rts
drivername dc.b "DEVS:ProNET/",0
even
******************
; -- The Main Loop
******************
MainLoop move.l priv_MsgBackPort(a5),a0
move.b MP_SIGBIT(a0),d2
move.b priv_ReadSignalBit(a5),d3
move.l priv_MsgPort(a5),a0
move.b MP_SIGBIT(a0),d4
moveq #0,d5
bset d2,d5
bset d3,d5
bset d4,d5 ;[d5] Signalmask to wait for
movem.l a6/d2-d5,-(sp)
Wait4Msg movem.l (sp),a6/d2-d5
bsr CheckWrites
move.l d5,d0
LIBCALL Wait
movem.l d0/d3/d4,-(sp)
btst d2,d0
bne doMSGBACK
wait1 movem.l (sp),d0/d3/d4
btst d3,d0
bne doREAD
wait2 movem.l (sp)+,d0/d3/d4
btst d4,d0
bne doMSG
bra Wait4Msg
; -- New Message at our MsgPort
doMSG move.l priv_MsgPort(a5),a0
LIBCALL GetMsg
tst.l d0
beq Wait4Msg ;no more messages
move.l d0,a2
move.w IO_COMMAND(a2),d0
cmp.w #PND_WRITE,d0
beq doWRITE
cmp.w #PND_ADDPORT,d0
beq doADDPORT
cmp.w #PND_REMPORT,d0
beq doREMPORT
move.b #IOERR_NOCMD,IO_ERROR(a2)
move.l a2,a1
LIBCALL ReplyMsg
bra doMSG
; -- Add a new port to this unit
doADDPORT move.w pnr_NetSourcePort(a2),d1
cmp.w #-1,d1
beq addport_getconf
cmp.w #-2,d1
beq addport_getnext
move.b #IOERR_OPENFAIL,IO_ERROR(a2)
* See if port already exists, portnumber in d1 now
lea priv_PortList(a5),a0
.loop0 move.l (a0),d0
beq.s .ok
move.l d0,a0
cmp.w pndp_PortNr(a0),d1
bne.s .loop0
* Sorry
move.b #PNDERR_PORTEXISTS,IO_ERROR(a2)
bra.s addport_ende
* No, add it!
.ok moveq #pndp_SizeOf,d0
moveq #0,d1
LIBCALL AllocMem
tst.l d0
beq.s addport_ende
move.l d0,a4
move.w pnr_NetSourcePort(a2),pndp_PortNr(a4)
move.l pnr_MsgPort(a2),pndp_MsgPort(a4)
lea priv_PortList(a5),a0
move.l (a0),(a4)
move.l a4,(a0)
bsr TryPendingReads
clr.b IO_ERROR(a2) ;Okay, port added
addport_ende move.l a2,a1
LIBCALL ReplyMsg
bra doMSG
addport_getconf move.l pnr_Data1(a2),a0
bsr getconfigstr
move.l d0,d3
beq.s .nostring
move.l d0,a0
bsr dec2long
move.w d1,pnr_NetSourcePort(a2)
move.l d3,a0
bsr freeconfigstr
bra doADDPORT
.nostring move.b #PNDERR_BADCONFIG,IO_ERROR(a2)
bra.s addport_ende
addport_getnext moveq #1,d1
lea priv_PortList(a5),a1
.next move.l a1,a0
.loop0 move.l (a0),d0
beq.s .notfound
move.l d0,a0
cmp.w pndp_PortNr(a0),d1
bne.s .loop0
addq.w #1,d1
bra.s .next
.notfound move.w d1,pnr_NetSourcePort(a2)
bra doADDPORT
; -- Remove current port
doREMPORT move.w pnr_NetSourcePort(a2),d2
lea priv_PortList(a5),a1
.find move.l a1,a3
move.l (a1),d0
beq.s .notfound
move.l d0,a1
cmp.w pndp_PortNr(a1),d2
bne.s .find
move.l (a1),d2
moveq #pndp_SizeOf,d0
LIBCALL FreeMem
move.l d2,(a3) ;Teil aus der Liste entfernt !!
move.l a2,a1
LIBCALL ReplyMsg
.notfound bra doMSG
; -- Do a WRITE command
doWRITE move.l a2,a1
lea priv_PendingWrites(a5),a0
LIBCALL AddTail
bsr TryPendingWrites
bra doMSG ;kurz und schmerzlos :-)
; -- A ProNET-Message was replied
doMSGBACK move.l priv_MsgBackPort(a5),a0
LIBCALL GetMsg
tst.l d0
beq wait1
move.l d0,a1 ;we don't need it any more.
moveq #0,d0
move.w MN_LENGTH(a1),d0
add.l #MN_SIZE,d0
LIBCALL FreeMem
bra.s doMSGBACK
; -- A new message from another Amiga is ready
doREAD move.l priv_ReadQuery(a5),a0 ;Do external driver magic..
jsr (a0)
* d0.w length (if NULL then exit!!!)
* d1 destination port
* d2 source port
ext.l d0
beq.s .ende
move.w d1,d7
move.w d2,d5
move.l d0,d6
addq.w #2,d6 ;include Source Port word
add.l #MN_SIZE+2,d0
move.l d0,d3
.tryagain moveq #MEMF_PUBLIC,d1 ;This part is the one and
LIBCALL AllocMem ;only thing in this device
tst.l d0 ;which I don't like, but
bne.s .memok ;it's the only solution!
move.l OurBase(pc),a6
move.l pnd_DosBase(a6),a6
moveq #50,d1
LIBCALL Delay
move.l 4.w,a6
move.l d3,d0
bra.s .tryagain
* Now get the data and build a Message
.memok move.l d0,a3
lea MN_SIZE+2(a3),a0
move.l priv_Read(a5),a1
jsr (a1)
move.w d5,MN_SIZE(a3)
move.w d6,MN_LENGTH(a3)
move.w d7,LN_NAME(a3)
move.l priv_MsgBackPort(a5),MN_REPLYPORT(a3)
move.b #NT_MESSAGE,LN_TYPE(a3)
lea priv_PendingReads(a5),a0
move.l a3,a1
LIBCALL AddTail
.ende bsr TryPendingReads
bsr TryPendingWrites
bra wait2
***
***
***
; -- Look at the history, 31-05-95 for reasons why we do this!
CheckWrites lea priv_PendingWrites(a5),a0
TSTLIST a0
beq.s .okay
move.b priv_ReadSignalBit(a5),d0
moveq #0,d1
bset d0,d1
moveq #-1,d0
LIBCALL SetSignal
.okay rts
***
***
***
; -- Try to send off all pending messages
TryPendingReads move.l a2,-(sp)
lea priv_PendingReads(a5),a3
move.l LH_HEAD(a3),a2
addq.l #4,a3
.looop cmp.l a2,a3
bne.s .doit
move.l (sp)+,a2
rts
.doit move.l a2,a4
move.l LN_SUCC(a2),a2
move.w LN_NAME(a4),d1
lea priv_PortList(a5),a0
.find move.l (a0),d0
beq.s .looop
move.l d0,a0
cmp.w pndp_PortNr(a0),d1
bne.s .find
move.l pndp_MsgPort(a0),d5
move.l a4,a1
LIBCALL Remove
move.l d5,a0
move.l a4,a1
LIBCALL PutMsg
bra.s .looop
; -- Try to send off all pending write requests
TryPendingWrites
move.l a2,-(sp)
lea priv_PendingWrites(a5),a3
move.l LH_HEAD(a3),a2
addq.l #4,a3
.looop cmp.l a2,a3
bne.s .doit
.busy move.l (sp)+,a2
rts
.doit move.l a2,a4
move.l LN_SUCC(a2),a2
move.l pnr_Data1(a4),a0
move.l pnr_Length1(a4),d0
addq.l #1,d0 ;round up to word boundary
bclr #0,d0
move.l pnr_Data2(a4),a1
move.l pnr_Length2(a4),d1
addq.l #1,d1 ;dito
bclr #0,d1
move.w pnr_NetDestPort(a4),d2
move.w pnr_NetSourcePort(a4),d3
move.l priv_Write(a5),a6
jsr (a6) ;Again some driver magic..
move.l 4.w,a6
tst.w d0
bne.s .busy
* IORequest done, reply it!
move.l a4,a1
LIBCALL Remove
move.l a4,a1
LIBCALL ReplyMsg
bra.s .looop
** -----------------------------------------------------------------------
**
**
**
**
**
** Routines for handling the configuration file
**
**
**
**
**
** -----------------------------------------------------------------------
; -- Obtain configuration string
getconfigstr ; a0 *line-identifier (e.g. 'HD2:') with ':'
; RETURNS d0 *line-string or NULL if it doesn't exist
movem.l d2-d7/a2-a6,-(sp)
move.l a0,a2
moveq #0,d4 ;RC
move.l 4.w,a6
move.l #$104,d0
moveq #0,d1
LIBCALL AllocMem
move.l d0,d6 ;Allocate FIB
beq .error
move.l OurBase(pc),a5
move.l pnd_DosBase(a5),a5
move.l a5,a6
move.l #configname,d1
moveq #ACCESS_READ,d2
LIBCALL Lock
move.l d0,d7
beq .nolock.mem
move.l d7,d1
move.l d6,d2
LIBCALL Examine
move.l d7,d1
LIBCALL UnLock ;So we've got the file length
move.l 4.w,a6
move.l d6,a0
move.l fib_Size(a0),d0
addq.l #1,d0
move.l d0,d5 ;[d5] configmemsize
move.l #MEMF_PUBLIC^MEMF_CLEAR,d1
LIBCALL AllocMem
tst.l d0
beq .nolock.mem
move.l d0,a3 ;[a3] configmem
move.l a3,a4
move.l a5,a6 ;Read file
move.l #configname,d1
move.l #MODE_OLDFILE,d2
LIBCALL Open
move.l d0,d7
beq.s .nofile
move.l d7,d1
move.l a3,d2
move.l d5,d3
subq.l #1,d3
LIBCALL Read
move.l d0,d2
move.l d7,d1
LIBCALL Close
cmp.l d2,d3
bne.s .nofile
.loop move.l a2,a0 ;Search string
move.l a3,a1
bsr.s .comparestr
tst.w d0
bne.s .next
.search0 move.b (a1)+,d0 ;Skip spaces until first
beq.s .nofile ;character
cmp.b #10,d0
beq.s .nofile
cmp.b #32,d0
bls.s .search0
move.l a1,d2 ;Get length of string
subq.l #1,d2
moveq #-5,d0
.search1 move.b (a1)+,d1
beq.s .searchok
cmp.b #10,d1
beq.s .searchok
dbra d0,.search1
.searchok neg.l d0 ;Extract string
move.l d0,d3
move.l 4.w,a6
moveq #MEMF_PUBLIC,d1
LIBCALL AllocMem
tst.l d0
beq.s .nofile
move.l d0,a0
move.l d3,(a0)+
move.l a0,d4
move.l d2,a1
.copyl0 move.b (a1)+,d1
move.b d1,(a0)+
beq.s .copyok
cmp.b #10,d1
bne.s .copyl0
.copyok clr.b -(a0)
bra.s .nofile
.next bsr.s .nextline
tst.w d0
beq.s .loop
.nofile move.l 4.w,a6
move.l a4,a1
move.l d5,d0
LIBCALL FreeMem
.nolock.mem move.l 4.w,a6
move.l d6,a1
move.l #$104,d0
LIBCALL FreeMem
.error move.l d4,d0
.ende movem.l (sp)+,d2-d7/a2-a6
rts
.comparestr moveq #0,d0
.compl0 move.b (a0)+,d1
move.b (a1)+,d2
bclr #5,d1
bclr #5,d2
cmp.b d1,d2
bne.s .comperr
tst.b d1
beq.s .compok
bra.s .compl0
.comperr moveq #-1,d0
.compok rts
.nextline moveq #0,d0
move.b (a3)+,d1
beq.s .nextlerr
cmp.b #10,d1
beq.s .nextlok
bra.s .nextline
.nextlerr moveq #-1,d0 ;end of file
.nextlok rts
; -- Dispose configuration string
freeconfigstr ; a0 *line-string got by 'getconfigstr'
move.l a6,-(sp)
move.l -(a0),d0
move.l a0,a1
move.l 4.w,a6
LIBCALL FreeMem
move.l (sp)+,a6
rts
configname dc.b "DEVS:ProNET.config",0
dosname dc.b "dos.library",0
even
** -----------------------------------------------------------------------
**
**
**
**
**
** Useful routines
**
**
**
**
**
** -----------------------------------------------------------------------
dec2long ; konvertiert Dezimalstring ab (a0) zu Longword in D1 !!
moveq #0,d1
.loop moveq #0,d0
move.b (a0)+,d0
sub.b #"0",d0
cmp.b #9,d0
bhi.s .oki
move.l d1,d2
lsl.l #3,d1
add.l d2,d1
add.l d2,d1
add.l d0,d1
bra.s .loop
.oki rts
long2dec ;Converts Long in d0 to Dec-String in (a0)+
tst.l d0
bne.s .0
move.b #"0",(a0)+
rts
.0 lea long2asciitab(pc),a1
moveq #9,d1
moveq #0,d6
.1 move.l (a1)+,d2
move.l d0,d3
moveq #-1,d4
.2 move.l d3,d5
sub.l d2,d3
cmp.l d5,d3
dbhi d4,.2
add.l d2,d3
move.l d3,d0
not.w d4
bne.s .3
tst.w d6
beq.s .4
.3 st d6
add.b #"0",d4
move.b d4,(a0)+
.4 dbra d1,.1
rts
long2asciitab dc.l 1000000000,100000000,10000000,1000000,100000
dc.l 10000,1000,100,10,1
include "A:ProNET/source/devio.s"
EndResident: